/*******************************************************************************
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *  
 * Copyright (c) 2011 Michael Chan.
 ******************************************************************************/
package com.google.code.solrdimension.test.services;

import java.io.IOException;
import java.net.MalformedURLException;
import java.util.List;

import javax.xml.transform.stream.StreamSource;

import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer;
import org.apache.solr.client.solrj.response.UpdateResponse;
import org.apache.solr.common.SolrInputDocument;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.oxm.Unmarshaller;
import org.springframework.stereotype.Service;

import com.google.code.solrdimension.core.DimensionFactory;
import com.google.code.solrdimension.core.DimensionInputDocument;
import com.google.code.solrdimension.test.constants.TestConstants;
import com.google.code.solrdimension.test.parsers.Add;
import com.google.code.solrdimension.test.parsers.Doc;
import com.google.code.solrdimension.test.parsers.Field;

/**
 * 
 * @author mhc
 * 
 */

@Service
public class SolrServiceImpl implements SolrService {

    @Autowired
    @Qualifier("testMarshaller")
    Unmarshaller marshaller;
    
    
    private static final String EXAMPLE_DATA_CLASS_PATH = "/exampledata.xml";

    private static Logger logger = LoggerFactory.getLogger(SolrServiceImpl.class);

    private SolrServer server = null;

    public SolrServer getSolrServer() throws SolrServerException {
        if (server == null) {
            initSolr();
        }
        return server;
    }

    private void initSolr() throws SolrServerException {
        try {
            server = new CommonsHttpSolrServer(TestConstants.SolrConf.END_POINT);
            if (server == null) {
                throw new SolrServerException("Cannot connect to Solr Server...");
            }

        } catch (MalformedURLException e) {
            logger.error("Please check URL format, cannot connect to Solr Server");
            e.printStackTrace();
        } catch (Exception e) {
            throw new SolrServerException("Cannot connect to Solr Server...");
        }
    }

    public boolean rebuildIndex() throws Exception {

        boolean result = false;

        boolean deleteResult = deleteIndex(true);
        boolean indexResult = indexProducts(true);

        if (deleteResult && indexResult) {
            result = true;
        } else {
            logger.error("Delete index success status: " + deleteResult);
            logger.error("Create index success status: " + indexResult);
        }

        return result;
    }

    /**
     * Index products
     * 
     * 
     * @param commit
     *            - Commit if set to true
     * @return True if index is successful
     * @throws IOException
     */
    private boolean indexProducts(boolean commit) throws Exception{
        //Make sure we have a solr server
        getSolrServer();
        
        boolean result = false;
        
        Add add = (Add)marshaller.unmarshal(new StreamSource(this.getClass().getResourceAsStream(EXAMPLE_DATA_CLASS_PATH)));
        
        List<Doc> docs = add.getDocs();
        
        for (Doc doc : docs){
            
            DimensionInputDocument inputDoc = DimensionFactory.getInstance().createSolrDimensionInputDocument(new SolrInputDocument());
            
            for (Field field : doc.getFields()){
                
                inputDoc.addField(field.getName(), field.getValue());
                
            }
            server.add(inputDoc.getSolrInputDocument());
            
        }
        
        if (commit){
            server.commit();
        }
        
        result = true;
        
        return result;
    }

    /**
     * Delete all products from index
     * 
     * @param commit
     *            - Commit if set to true
     * @return
     * @throws IOException
     */
    private boolean deleteIndex(boolean commit) throws SolrServerException, IOException {
        boolean result = false;
        UpdateResponse response = getSolrServer().deleteByQuery("*:*");

        int status = response.getStatus();

        // status 0 from solr means good
        if (status == 0) {
            result = true;
        }

        if (commit)
            getSolrServer().commit();
        return result;
    }


}
